#include <opencv2/opencv.hpp>
#include <dlib/opencv.h>
#include <dlib/image_processing/frontal_face_detector.h>
#include <dlib/image_processing.h>
#include <nadjieb/mjpeg_streamer.hpp>
#include <chrono>
#include <iomanip>

using namespace std;
using namespace dlib;

// 配置参数
#define DETECTION_INTERVAL 10  // 每隔多少帧检测一次人脸
#define PORT 8080              // 视频流端口

int main() {
    // 初始化视频捕获
    cv::VideoCapture cap(0);
    if (!cap.isOpened()) {
        cerr << "无法打开摄像头" << endl;
        return -1;
    }

    // 初始化MJPEG流服务器
    nadjieb::MJPEGStreamer streamer;
    streamer.start(PORT);
    
    // JPEG编码参数
    std::vector<int> params = {cv::IMWRITE_JPEG_QUALITY, 90};

    // 初始化人脸检测器和特征点检测器
    frontal_face_detector detector = get_frontal_face_detector();
    shape_predictor sp;
    try {
        deserialize("/home/hhy212306170/practice/model/shape_predictor_68_face_landmarks.dat") >> sp;
    } catch (exception& e) {
        cerr << "加载人脸特征点模型失败: " << e.what() << endl;
        return -1;
    }

    int frame_count = 0;
    cv::Mat frame;

    cout << "视频流已启动，访问 http://localhost:" << PORT << "/bgr" << endl;

    while (true) {
        // 捕获帧
        cap >> frame;
        if (frame.empty()) {
            cerr << "获取帧失败" << endl;
            break;
        }

        // 每隔DETECTION_INTERVAL帧检测一次人脸
        if (frame_count % DETECTION_INTERVAL == 0) {
            // 转换为dlib格式
            cv_image<bgr_pixel> dlib_img(frame);
            
            // 检测人脸
            std::vector<rectangle> faces = detector(dlib_img);
            
            // 绘制人脸框
            for (const auto& face : faces) {
                cv::rectangle(frame, 
                    cv::Point(face.left(), face.top()),
                    cv::Point(face.right(), face.bottom()),
                    cv::Scalar(0, 255, 0), 2);
            }
        }

        frame_count++;

        // 推送视频流
        std::vector<uchar> buff_bgr;
        cv::imencode(".jpg", frame, buff_bgr, params);
        streamer.publish("/bgr", std::string(buff_bgr.begin(), buff_bgr.end()));

        // 按键检测，ESC退出
        if (cv::waitKey(10) == 27) {
            break;
        }
    }

    // 释放资源
    streamer.stop();
    cap.release();
    cout << "程序已退出" << endl;
    return 0;
}